package org.glow.changgou.seckill.timer;



import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.glow.changgou.entity.DateUtil;
import org.glow.changgou.entity.SystemConstants;
import org.glow.changgou.seckill.dao.SeckillGoodsMapper;
import org.glow.changgou.seckill.pojo.SeckillGoods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 定时任务 spring task(多线程)
 * 1.开始spring task
 * 2.在执行的方法上修饰一个注解  注解中指定何时执行即可
 *
 * @author glow
 * @version 1.0
 * @package org.glow.changgou.seckill.timer *
 * @since 1.0
 */
@Component
public class SeckillGoodsPushTask {

    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    //反复被执行的方法 隔5秒钟执行一次
    @Scheduled(cron = "0/5 * * * * ?")
    public void loadGoodsPushRedis() {
        //1.获取当前的时间对应的5个时间段
        List<Date> dateMenus = DateUtil.getDateMenus();
        //2.循环遍历5个时间段 获取到时间的日期
        for (Date starttime : dateMenus) {


            String extName =  DateUtil.data2str(starttime,DateUtil.PATTERN_YYYYMMDDHH);
            //3.将循环到的时间段 作为条件 从数据库中执行查询 得出数据集


            /**
             * select * from tb_seckill_goods where
             stock_count>0
             and `status`='1'
             and start_time > 开始时间段
             and end_time < 开始时间段+2hour  and id  not in (redis中已有的id)
             */
            LambdaQueryWrapper<SeckillGoods> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SeckillGoods::getStatus,"1");
            queryWrapper.gt(SeckillGoods::getStartTime,starttime);
            queryWrapper.lt(SeckillGoods::getEndTime,DateUtil.addDateHour(starttime, 2));


            //排除掉redis已有的商品
            Set keys = redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + extName).keys();
            if(keys!=null && keys.size()>0) {
                queryWrapper.notIn(SeckillGoods::getId,keys);
            }

            List<SeckillGoods> seckillGoods = seckillGoodsMapper.selectList(queryWrapper);

            //4.将数据集存储到redis中(key field value的数据格式 )

            /**
             * key    field (id:1)   value(商品的数据pojo)

                                          field (id:2)   value(商品的数据pojo)

             key(时间段:20221009)      field (id:3)   value(商品的数据pojo)

                                          field (id:4)   value(商品的数据pojo)

             *
             *
             */

            for (SeckillGoods seckillGood : seckillGoods) {
                //SeckillGoods_
                redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + extName).put(seckillGood.getId(),seckillGood);
                //设置有效期
                redisTemplate.expireAt(SystemConstants.SEC_KILL_GOODS_PREFIX + extName,DateUtil.addDateHour(starttime, 2));
                //商品数据队列存储,防止高并发超卖
                Long[] ids = pushIds(seckillGood.getStockCount(), seckillGood.getId());
                redisTemplate.boundListOps("SeckillGoodsCountList_"+seckillGood.getId()).leftPushAll(ids);
                    //自增计数器
                redisTemplate.boundHashOps("SeckillGoodsCount").increment(seckillGood.getId(),seckillGood.getStockCount());
            }


        }
    }
    /***
     * 将商品ID存入到数组中
     * @param len:长度
     * @param id :值
     * @return
     */
    public Long[] pushIds(int len,Long id){
        Long[] ids = new Long[len];
        for (int i = 0; i <ids.length ; i++) {
            ids[i]=id;
        }
        return ids;
    }
    /*public static void main(String[] args) {
        //获取所有的时间段(根据当前的时间获取5个)
        List<Date> dateMenus = DateUtil.getDateMenus();

        for (Date dateMenu : dateMenus) {
            System.out.println(dateMenu);
        }
    }*/
}
